import { IPSDEForm, IPSDEFormPage } from "@ibiz/dynamic-model-api";
import { SheetUtil, Util } from "../../utils";

/**
 * @description 虚拟表单服务
 * @export
 * @class AppVisualFormService
 */
export default class AppVisualFormService {

    /**
     * @description 部件实例
     * @private
     * @type {*}
     * @memberof AppVisualFormService
     */
    private controlInstance!: IPSDEForm;

    /**
     * @description 表单数据
     * @private
     * @type {*}
     * @memberof AppVisualFormService
     */
    public visualCtrlData: any = {};

    /**
     * 默认配置参数
     *
     * @type {*}
     * @memberof AppVisualFormService
     */
    public sheetConfig!: any;

    /**
     * 控件位置
     *
     * @type {*}
     * @memberof AppVisualFormService
     */
    public position!: any;

    /**
     * @description 表单项Map
     * @type {Map<string, any>}
     * @memberof AppVisualFormService
     */
    public formItemMap: Map<string, any> = new Map();

    /**
     * @description 表单位置信息Map
     * @type {Map<string, any>}
     * @memberof AppVisualFormService
     */
    public positionMap: Map<string, any> = new Map();

    /**
     * Creates an instance of AppVisualFormService.
     * @param {*} options
     * @memberof AppVisualFormService
     */
    constructor(options: any) {
        this.controlInstance = options.controlInstance;
        this.sheetConfig = options.sheetConfig;
        this.position = options.position;
    }

    /**
     * @description 初始化虚拟表单
     * @param {*} data 表单数据
     * @memberof AppVisualFormService
     */
    public initVisualCtrl(data: any) {
        this.visualCtrlData = data;
        this.initFormConf();
        this.initFormCell();
        this.initFormDetails();
        this.mountedFormDetails();
    }

    /**
     * @description 初始化表单conf
     * @memberof AppVisualFormService
     */
    public initFormConf() {
        let tempSheetConfig: any = {};
        if (this.sheetConfig && this.sheetConfig.config) {
            tempSheetConfig = Util.deepCopy(this.sheetConfig.config);
        }
        if (!tempSheetConfig.borderInfo) {
            Object.assign(tempSheetConfig, this.initSheetConfig(this.position));
        }
        const originalConf = (window as any).luckysheet.getConfig();
        Util.deepObjectMerge(tempSheetConfig, originalConf);
        (window as any).luckysheet.setConfig(tempSheetConfig);
    }

    /**
     * @description 初始化表单sheet配置参数
     * @param {*} data
     * @memberof AppVisualFormService
     */
    public initSheetConfig(position: any) {
        const borderInfoConfig = [
            {
                "rangeType": "range",
                "borderType": "border-all",
                "style": "1",
                "color": "#909399",
                "range": [{
                    "row": [position.startRow, position.startRow + position.row - 1],
                    "column": [position.startCol, position.startCol + position.col - 1]
                }]
            }
        ];
        return {
            borderInfo: borderInfoConfig
        }
    }

    /**
     * @description 初始化表单单元格数据
     * @memberof AppVisualFormService
     */
    public initFormCell() {
        let tempSheetData: any = {};
        if (this.sheetConfig && this.sheetConfig.data) {
            tempSheetData = Util.deepCopy(this.sheetConfig.data);
        }
        if (tempSheetData && tempSheetData.length > 0) {
            tempSheetData.forEach((element: any) => {
                (window as any).luckysheet.setCellValue(element.r, element.c, element.v);
            });
        }
    }

    /**
 * @description 初始化表单Detail
 * @memberof AppVisualFormService
 */
    public initFormDetails() {
        let curPosition = { row: 0, col: 0 };
        if (this.controlInstance.getPSDEFormPages() && (this.controlInstance.getPSDEFormPages() as IPSDEFormPage[]).length > 0) {
            for (let i = 0; i < (this.controlInstance.getPSDEFormPages() as IPSDEFormPage[]).length; i++) {
                this.initDetail((this.controlInstance.getPSDEFormPages() as IPSDEFormPage[])[i], curPosition);
            }
        }
    }

    /**
     * @description 初始化详情
     * @memberof AppVisualFormService
     */
    public initDetail(parentItem: any, position: any): any {
        if (parentItem && Object.is(parentItem.detailType, 'FORMITEM') && (parentItem.hidden !== true)) {
            this.formItemMap.set(parentItem.codeName, parentItem);
            const curPosition = Util.deepCopy(position);
            position.col += parentItem.getPSLayoutPos().colMD;
            if (position.col > 24) {
                position.row += 1;
                position.col = parentItem.getPSLayoutPos().colMD;
                Object.assign(curPosition, { startCol: 0, endCol: position.col });
            } else {
                Object.assign(curPosition, { startCol: curPosition.col, endCol: position.col });
            }
            Object.assign(curPosition, position);
            Object.assign(curPosition, { codeName: parentItem.codeName, position: this.compEditorPosition(curPosition) });
            this.positionMap.set(parentItem.codeName, Util.deepCopy(curPosition));
        } else {
            if (parentItem && Object.is(parentItem.detailType, 'GROUPPANEL')) {
                if (position.row > 0) {
                    position.row += 1;
                }
                position.col = 0;
            }
            if (parentItem && parentItem.getPSDEFormDetails instanceof Function) {
                const formDetails = parentItem?.getPSDEFormDetails();
                if (formDetails && formDetails.length > 0) {
                    for (let i = 0; i < formDetails.length; i++) {
                        this.initDetail(formDetails[i], position);
                    }
                }
            }
        }
    }

    /**
     * @description 挂载表单项集合
     * @memberof AppVisualFormService
     */
    public mountedFormDetails() {
        const mergeConf = {};
        for (let key of this.positionMap.keys()) {
            const item = this.positionMap.get(key);
            const formItem = this.formItemMap.get(key);
            // 设置表单项lab
            (window as any).luckysheet.setCellValue(item.row, item.startCol, formItem.caption);
            // 设置表单项content区合并单元格
            Object.assign(mergeConf, {
                [`${item.row}_${item.startCol + 1}`]: {
                    r: item.row,
                    c: item.startCol + 1,
                    rs: 1,
                    cs: item.endCol - item.startCol - 1
                }
            });
            (window as any).luckysheet.setCellValue(item.row, item.startCol + 1, { codeName: key, v: this.visualCtrlData[key], bg: '#dfda94', mc: { r: item.row, c: item.startCol + 1, rs: 1, cs: item.endCol - item.startCol - 1 } });
            //  设置合并单元格中其他单元格的合并
            if (item.endCol - item.startCol > 1) {
                for (let _col = item.startCol + 2; _col < item.endCol; _col++) {
                    (window as any).luckysheet.setCellValue(item.row, _col, { mc: { r: item.row, c: item.startCol + 1 } });
                }
            }
        }
        const originalConf = (window as any).luckysheet.getConfig();
        Util.deepObjectMerge(originalConf, { merge: mergeConf });
        (window as any).luckysheet.setConfig(originalConf);
    }

    /**
     * @description 计算编辑器位置
     * @param {*} item 项位置信息
     * @return {*} 
     * @memberof AppVisualFormService
     */
    public compEditorPosition(item: any) {
        let left = 0,
            top = 0,
            width = 0,
            height = 0;
        // left
        for (let i = 0; i < item.startCol + 1; i++) {
            left += (window as any).luckysheet.getColumnWidth([i])[i] + 1;
        }
        // top
        for (let i = 0; i < item.row; i++) {
            top += (window as any).luckysheet.getRowHeight([i])[i] + 1;
        }
        // width
        for (let i = item.startCol + 1; i < item.endCol; i++) {
            width += (window as any).luckysheet.getColumnWidth([i])[i] + 1;
        }
        width -= 2;
        // height
        height += (window as any).luckysheet.getRowHeight([item.row])[item.row] + 1 - 2;
        return { left, top, width, height };
    }

    /**
     * @description 控件清除
     * @memberof AppVisualFormService
     */
    public handClearAll() {
        SheetUtil.getElement('.app-visual-ctrl-item').remove();
        (window as any).luckysheet.setConfig({
            merge: {},
            columnlen: {},
            borderInfo: {}
        });
    }

    /**
 * @description 判断当前激活项控件
 * @param {*} position
 * @return {*} 
 * @memberof AppVisualFormService
 */
    public checkSelectedCtrl(position: any) {
        const curPosition = this.getCtrlRange(this.position);
        if (curPosition) {
            const tempPosition = {
                start_r: curPosition.top,
                start_c: curPosition.left,
                end_r: curPosition.top + curPosition.height,
                end_c: curPosition.left + curPosition.width
            };
            if ((position.start_r >= tempPosition.start_r) &&
                (position.start_c >= tempPosition.start_c) &&
                (position.end_r <= tempPosition.end_r) &&
                (position.end_c <= tempPosition.end_c)) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
    * @description 获取表单区域
    * @param {*} position 位置信息
    * @memberof AppVisualFormService
    */
    public getCtrlRange(position: any) {
        let left = 0,
            top = 0,
            width = 0,
            height = 0,
            row = position.row,
            col = position.col;
        if (position.startCol) {
            for (let i = 0; i < position.startCol; i++) {
                const result = (window as any).luckysheet.getColumnWidth([i]);
                left += result[i] + 1;
            }
        }
        if (position.startRow) {
            for (let i = 0; i < position.startRow; i++) {
                const result = (window as any).luckysheet.getRowHeight([i]);
                top += result[i] + 1;
            }
        }
        if (position.col) {
            for (let i = position.startCol; i < position.col; i++) {
                const result = (window as any).luckysheet.getColumnWidth([i]);
                width += result[i] + 1;
            }
        }
        if (position.row) {
            for (let i = position.startRow; i < position.row; i++) {
                const result = (window as any).luckysheet.getRowHeight([i]);
                height += result[i] + 1;
            }
        }
        return { left, top, width, height, row, col };
    }
}